home *** CD-ROM | disk | FTP | other *** search
-
- /**************************************************************************/
- Figure 1 - In-Line Assembly Code for exec() Function
-
- #pragma inline
- /**************/
- exec(char *program, char *argument) /* new ANSI way of declaring args */
- {
- /* The rules of this game are rather too involved to explain here. See
- Ray Duncan's <i>Advanced MSDOS<d>, chapter 10, for a lucid explanation
- of the MSDOS's ``exec'' function. This is done in the ``large'' model so
- pointers will all be 4 bytes long and coding will be straightforward.*/
- char comline[30]; /* to construct command line */
- struct{ /* structure needed by DOS 0x4b service */
- unsigned envseg;
- char *command,*fcb1,*fcb2;
- } paramblock,*pbptr;
-
- paramblock.envseg=0; /* keep the old environment */
- comline[0] = strlen(argument); /* first char: length of line */
- strcpy(comline+1,argument);
- strcat(comline,"\r"); /* terminate with 0xd */
- paramblock.command = comline;
- paramblock.fcb1=paramblock.fcb2=(char *)0xffffffff; /* Ignore fcb's */
- pbptr = ¶mblock;
- asm push ds /* DS & BP must be saved. Turbo saves SI & DI */
- asm push bp
- /* The next two routines work because this is the LARGE model and
- pointers are 32-bit entities and work with lds & les. Cute, no? */
- asm lds dx,program /* DS:DX pointed to program path */
- asm les bx,pbptr /* ES:BX pointed to parameter structure */
- asm mov word ptr cs:fill[0],ss /* save SS & SP */
- asm mov word ptr cs:fill[2],sp
- asm jmp next
- asm fill dw 0,0 /* store SS & SP in code segment */
- next:
- asm mov al,0
- asm mov ah,4bh
- asm int 21h /* do exec call */
- asm cli
- asm mov ss,cs:fill[0] /* restore SS & SP */
- asm mov sp,cs:fill[2]
- asm sti
- asm pop bp
- asm pop ds
- }
- /*******************************************************************/
-
-
-
-
- /*Figure 2 - Getting Rid of Resident Programs*/
-
- /* LARGE MODEL USED SO POINTERS ARE 32 BITS.
- This compiles to 5.6K, which supports Borland's claim to
- relatively tight code. Incidentally, I can do the same in 2.3K in DeSmet C
- and about 1K in assembler. Neither coding is half so simple, however.
- This sort of direct manipulation of MSDOS allocation headers
- is an example of ill-behaved programming at its most incorrigible. But don't
- long C pointers make crime EASY??*/
-
- #include <dos.h>
- #include <stdio.h>
- #define RSHIFT 1 /* corresponding bits on shift state byte @ 00:417H */
- #define LSHIFT 2
- #define ALT 8
- #define TESTIT (RSHIFT | LSHIFT | ALT)
- #define TICKINT 8
- #define NEWTICK 0x80
- #define FINI 0x5a
- char intable[0x400],*shiftptr=(char *) 0x417L;
- typedef struct { /* MSDOS allocation header format */
- char flag; /* Either 5Ah for end or 4Dh for not end */
- unsigned nextpsp,paragraphs;
- } HEAD;
- HEAD *header;
- extern unsigned _psp;
- unsigned meminstall; /* how much memory is installed in PC? */
- /******************/
- void interrupt tickhandler()
- { /* check shift state for three shifts depressed */
-
- if( (*shiftptr & TESTIT) == TESTIT) deallocate();
- geninterrupt(NEWTICK); /* chain the interrupt */
- }
- /***************/
- deallocate()
- {
- HEAD *nextheader;
-
- /* _AX is a "pseudovariable" which can be used to get or change
- the value stored in AX. The possibilities are mind-boggling. */
- _AX=0xe00+7; /* just a beep to show something happened */
- geninterrupt(0x10);
- memcpy(NULL,intable,0x400); /* restore old int table */
- nextheader = MK_FP(_psp + header->paragraphs,0);
- nextheader->flag = FINI; /* tell MSDOS that everything's free above */
- nextheader->nextpsp = 0;
- nextheader->paragraphs = meminstall - 1 - _psp - header->paragraphs;
- }
- /*********************/
- main()
- {
- char **newtick,**oldtick; /*just so it's 32 bits. char * is a convenience. */
-
- header = MK_FP(_psp - 1, 0); /* point to TSR's allocation header */
- newtick = MK_FP(0,4*NEWTICK); /* swap interrupt vectors */
- oldtick = MK_FP(0,4*TICKINT);
- disable(); /* stop hardware */
- *newtick = *oldtick;
- *oldtick = (char *) tickhandler; /* put interrupt address into table */
- enable();
- memcpy(intable,NULL,0x400); /* save old interrupt table */
- geninterrupt(0x12); /*how much memory installed? */
- meminstall = _AX*0x40; /* store amount in paragraphs */
- /* Note that TurboC concatenates strings for you. */
- puts("\nDEINSTALLATION PROGRAM INSTALLED\n"
- " Press Alt-Leftshift-Rightshift\n"
- "to deinstall subsequent resident programs.\n" );
- keep(0,_SS - _psp +1); /* lop off stack, terminate & stay...*/
- }/* keep(0,n) uses DOS function 31h to set aside n paragraphs of memory */
- /********************/
-